using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using TianShiProject.EntityFrameworkCore;
using TianShiProject.Localization;
using TianShiProject.MultiTenancy;
using TianShiProject.Web.Menus;
using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.Account.Web;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.AutoMapper;
using Volo.Abp.FeatureManagement;
using Volo.Abp.Identity.Web;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement.Web;
using Volo.Abp.SettingManagement.Web;
using Volo.Abp.Swashbuckle;
using Volo.Abp.TenantManagement.Web;
using Volo.Abp.UI.Navigation.Urls;
using Volo.Abp.UI;
using Volo.Abp.UI.Navigation;
using Volo.Abp.VirtualFileSystem;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Text.Encodings.Web;
using System.Text.Unicode;
using Volo.Abp.Json;
using Alipay.AopSdk.AspnetCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;

namespace TianShiProject.Web
{
    [DependsOn(
        typeof(TianShiProjectHttpApiModule),
        typeof(TianShiProjectApplicationModule),
        typeof(TianShiProjectEntityFrameworkCoreModule),
        typeof(AbpAutofacModule),
        typeof(AbpIdentityWebModule),
        typeof(AbpSettingManagementWebModule),
        typeof(AbpAccountWebIdentityServerModule),
        typeof(AbpAspNetCoreMvcUiBasicThemeModule),
        typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
        typeof(AbpTenantManagementWebModule),
        typeof(AbpAspNetCoreSerilogModule),
        typeof(AbpSwashbuckleModule)
        )]
    public class TianShiProjectWebModule : AbpModule
    {
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
            {
                options.AddAssemblyResource(
                    typeof(TianShiProjectResource),
                    typeof(TianShiProjectDomainModule).Assembly,
                    typeof(TianShiProjectDomainSharedModule).Assembly,
                    typeof(TianShiProjectApplicationModule).Assembly,
                    typeof(TianShiProjectApplicationContractsModule).Assembly,
                    typeof(TianShiProjectWebModule).Assembly
                );
            });
        }

        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var hostingEnvironment = context.Services.GetHostingEnvironment();
            var configuration = context.Services.GetConfiguration();

            ConfigureUrls(configuration);
            ConfigureBundles();
            ConfigureAuthentication(context, configuration);
            ConfigureAutoMapper();
            ConfigureVirtualFileSystem(hostingEnvironment);
            ConfigureLocalizationServices();
            ConfigureNavigationServices();
            ConfigureAutoApiControllers();
            ConfigureSwaggerServices(context.Services);
            //原样输出
            context.Services.AddControllers().AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
                options.JsonSerializerOptions.PropertyNamingPolicy = null;
            });
            //context.Services.Configure<AbpJsonOptions>(options =>
            //{
            //    options.DefaultDateTimeFormat = "yyyy-MM-dd HH:mm:ss";
            //});
            //配置跨域
            context.Services.AddCors(options =>
            {
                options.AddDefaultPolicy(p =>
                {
                    p.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
                });
            });
            //配置支付宝依赖
            context.Services.AddAlipay(options =>
            {
                options.AlipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh0O7x/PcXWw3iCU/dE2oTABbtksHkmz72zdRr4tYM3+RdV12ERMdFVn9LVyHxsF8cqhQ8Fpz+JSnrPA6ZLjuftTDmpO17ShodW486FDqLu2V8LHpFYar6oXajq/PguuEt/OKLYgL1+QRtU/aaKoFm6eNmiCbhjIvNBs2SLm/ZUj5+0K5bMHL5CXv+i+kkmDEHNuAgUxdvnAf1aKTA1gfzRL3CzOoeF541WbWew4BBlv3meEX4xM2HIT9T6pT+0UUi+vroSf75fesCixmnCL6sHilYY91Xuni4+rXCQKbZvDzHuI4tzFCbGHxINe7Ep1mWjpudIncZ22fIHubqzx6WQIDAQAB";
                options.AppId = "2021000118639275";
                options.CharSet = "UTF-8";
                options.Gatewayurl = "https://openapi.alipaydev.com/gateway.do";
                options.PrivateKey = "MIIEogIBAAKCAQEAymn6jSFDh4aD4NzlL8nZ8BMeifI+RIYQNhXgsIjkpBcFrSOhXu/tGXiRWUhEEQB875x+2wKalYbacub9L6raC1iu0Ese8KNhiYuceU+0eYBUxtMO1iKr6YzLXo+4c66isC4s0iYysz6StOsDndxkKmYp3uJViBClGx9GogVPUcbOTrfWW03J4xIxVelTWNtvzLzFwmfDaHgM+yWBWZ3p6FAkTlFb6R0LBGqZ6GVc/4kmLYLp6SFXzYlQmAwAMM9z26dJKIiBkWZoS1NUq7rCtsWdrqG8pvYgwaBFy8eZudnceedUJjMqsKqVhp6UkF0eEZv7SATYPintu2/AfFjhSQIDAQABAoIBAGDwrqFGrAvNHX3k7RKdDnZPAdI5JR82Qa9VfP2vIimAKSTJqrBIIfqP5rSmyoqF/E/ZWFvVfGleY2KiQ+G/ZpwGhfqV76R56u2v4mmrBZknH/L1A+cERecdmgyYslMc8SeFhcvDpYZ40lQ5Ncs10PcJZMYtCZ+XsSszKGXSOzHDNUfKWPsISXge9tsZjrzyjwGEOy2g42bRQaRHNcS7J7FGnwH3959EV3c7VGsGflq6p+A2OdFXF7mKshNlbSbKUeUWQf/HoWSd+4hlwKf58yqM87O+m5Zo5CZ0jlaEG130gZsqkNfBVoRSDL27B6lI3d/9NcMfZymwKX26GkmQZO0CgYEA9TmURPDzNCtehwotnqKaHf+OIIYtxlGGsmGol7IWWhv45ZDeQPmcV4UIGa3VzkaEQQmYR+8CWm0cEm6GECP3p4EFFvE+P5kuVji2W7WFym8Qmpa7cbfXwaxaBANI6QrqdDkfIhBOEPHS5KQ7wcFMwPD/2aYIP/tWjXd3j4wZ6+MCgYEA007W2BgnLhsCOfFshsOBsnf668m0REvIHs9YRkTfS4K4UYCzvy0IoqJLj2vCjBg3/S+cnB/YKycJNamjKkrJKQ34yDmsugLcH8F7DvQEHvYJo6KaJLB1XpdFYsyPrCPKbBjps5AyQaP0dzab+JgaVFP1/aDeMbIO0TjjcyEMHeMCgYA2boB1yRICy3mg+eZkZu1UqUwP9hilA6WlZL36ZgJGIB1gP4bF32IPnyzMHmTt84MZuJp/pRLdpYhsovHJFWK8YIwTqprJnSPG6bG4q5M1+u8xkTGsLUWL7MjSSTRe3hhqkd9SPVJGupa4P6gv+sshrJzt38fHA/ATWKhGSa/bRwKBgF4xgLfnXF/DDmUB55zTPddugF3nFgJzvYtuZi08ukUQylUaiAWqb3T/36rZIGoOybaFKMy3rUbfKc3QBrntiGpSnhmzC/oHGFTXjKGHyOZ8SqO08f1043z89aMrCMh1U+CH4nV2y9BS48DYiQJx2xrIKpmawjFo7A37y/ggPSR9AoGAWzJFaQd5FRcvmNn/rprGMbXF2rrRt6ZaN12W5iUdCNFsTNnfSuOwudRBH4l8ljlrVRIN2sJ8YYExpT8XMqg1joAeIyB/x6G2BwxyO1ByGc1kbz2rv1pp1Zowv2biiHw9wxM0dbs+GW64mDQ0JcvhqvcUQjI7i4DYI5sZux2gWaI=";
                options.SignType = "RSA2";
                options.Uid = "2088621956724035";
            });
        }

        private void ConfigureUrls(IConfiguration configuration)
        {
            Configure<AppUrlOptions>(options =>
            {
                options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
            });
        }

        private void ConfigureBundles()
        {
            Configure<AbpBundlingOptions>(options =>
            {
                options.StyleBundles.Configure(
                    BasicThemeBundles.Styles.Global,
                    bundle =>
                    {
                        bundle.AddFiles("/global-styles.css");
                    }
                );
            });
        }

        private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddAuthentication()
                .AddJwtBearer(options =>
                {
                    options.Authority = configuration["AuthServer:Authority"];
                    options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
                    options.Audience = "TianShiProject";
                });
        }


        #region tokenJWT
        //private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
        //{
        //    context.Services.AddAuthentication(x =>
        //    {
        //        //x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        //        //x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        //    }).AddJwtBearer(x =>
        //    {
        //        x.RequireHttpsMetadata = false;
        //        x.SaveToken = true;
        //        x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
        //        {
        //            ValidateIssuerSigningKey = true,
        //            ValidateIssuer = false,
        //            ValidateAudience = false,
        //            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(configuration["Authentication:SecretKey"]))
        //        };
        //    });
        //}
        #endregion


        private void ConfigureAutoMapper()
        {
            Configure<AbpAutoMapperOptions>(options =>
            {
                options.AddMaps<TianShiProjectWebModule>();
            });
        }

        private void ConfigureVirtualFileSystem(IWebHostEnvironment hostingEnvironment)
        {
            if (hostingEnvironment.IsDevelopment())
            {
                Configure<AbpVirtualFileSystemOptions>(options =>
                {
                    options.FileSets.ReplaceEmbeddedByPhysical<TianShiProjectDomainSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}TianShiProject.Domain.Shared"));
                    options.FileSets.ReplaceEmbeddedByPhysical<TianShiProjectDomainModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}TianShiProject.Domain"));
                    options.FileSets.ReplaceEmbeddedByPhysical<TianShiProjectApplicationContractsModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}TianShiProject.Application.Contracts"));
                    options.FileSets.ReplaceEmbeddedByPhysical<TianShiProjectApplicationModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}TianShiProject.Application"));
                    options.FileSets.ReplaceEmbeddedByPhysical<TianShiProjectWebModule>(hostingEnvironment.ContentRootPath);
                });
            }
        }

        private void ConfigureLocalizationServices()
        {
            Configure<AbpLocalizationOptions>(options =>
            {
                options.Languages.Add(new LanguageInfo("ar", "ar", "العربية"));
                options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
                options.Languages.Add(new LanguageInfo("en", "en", "English"));
                options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)"));
                options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
                options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish"));
                options.Languages.Add(new LanguageInfo("fr", "fr", "Français"));
                options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
                options.Languages.Add(new LanguageInfo("is", "is", "Icelandic", "is"));
                options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
                options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
                options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
                options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
                options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
                options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
                options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
                options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
                options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de"));
                options.Languages.Add(new LanguageInfo("es", "es", "Español"));
            });
        }

        private void ConfigureNavigationServices()
        {
            Configure<AbpNavigationOptions>(options =>
            {
                options.MenuContributors.Add(new TianShiProjectMenuContributor());
            });
        }

        private void ConfigureAutoApiControllers()
        {
            Configure<AbpAspNetCoreMvcOptions>(options =>
            {
                options.ConventionalControllers.Create(typeof(TianShiProjectApplicationModule).Assembly);
            });
        }

        private void ConfigureSwaggerServices(IServiceCollection services)
        {
            services.AddAbpSwaggerGen(
                options =>
                {
                    options.SwaggerDoc("v1", new OpenApiInfo { Title = "TianShiProject API", Version = "v1" });
                    options.DocInclusionPredicate((docName, description) => true);
                    options.CustomSchemaIds(type => type.FullName);
                    #region 开启Swagger认证
                //    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                //    {

                //        Description = "在下框中输入请求头中需要添加Jwt授权Token：Bearer Token",
                //        Name = "Authorization",
                //        In = ParameterLocation.Header,
                //        Type = SecuritySchemeType.ApiKey,
                //        BearerFormat = "JWT",
                //        Scheme = "Bearer"
                //    });

                //    options.AddSecurityRequirement(new OpenApiSecurityRequirement
                //{
                //    {
                //        new OpenApiSecurityScheme
                //        {
                //            Reference = new OpenApiReference {
                //                Type = ReferenceType.SecurityScheme,
                //                Id = "Bearer"
                //            }
                //        },
                //        new string[] { }
                //    }
                //});
                    #endregion
                }
            );
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseAbpRequestLocalization();

            if (!env.IsDevelopment())
            {
                app.UseErrorPage();
            }

            app.UseCorrelationId();
            app.UseStaticFiles();
            app.UseRouting();
            //使用跨域
            app.UseCors();
            app.UseAuthentication();
            app.UseJwtTokenMiddleware();

            if (MultiTenancyConsts.IsEnabled)
            {
                app.UseMultiTenancy();
            }

            app.UseUnitOfWork();
            app.UseIdentityServer();
            app.UseAuthorization();
            app.UseSwagger();
            app.UseAbpSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "TianShiProject API");
            });
            app.UseAuditing();
            app.UseAbpSerilogEnrichers();
            app.UseConfiguredEndpoints();
        }
    }
}
